import { ref, onUnmounted, watch, h, unref } from 'vue';
import type { WatchStopHandle } from 'vue';
import { Tag } from 'ant-design-vue';
import { VxeGridPropTypes } from 'vxe-table';

import type { DynamicProps } from '#/utils';
import type { FormActionType } from '@/components/Form';

import { FetchParams } from '../types/table';
import { FormModeEnum } from '@/enums/formEnum';

import { formatToDate } from '@/utils/date';
import { isProdMode } from '@/utils/env';
import Icon from '@/components/Icon/Icon.vue';
import { isBoolean, isString, isNumber, isArray } from '@/utils/is';
import { getDynamicProps } from '@/utils';
import { error } from '@/utils/log';
import { expandAndToString } from '@/utils/common';

import type { TableProps, AdColumn, TableActionType } from '../types/table';

type Props = Partial<DynamicProps<TableProps>>;

type UseTableMethod = TableActionType & {
  getForm: () => FormActionType;
};

/**
 * 使用高级表格
 * @param tableProps 表格选项
 * @returns 高级表格对象
 */
export function useAdVxeTable(tableProps?: Props): [
  (instance: TableActionType, formInstance: UseTableMethod) => void,
  TableActionType & {
    getForm: () => FormActionType;
  },
] {
  const tableRef = ref<Nullable<TableActionType>>(null);
  const loadedRef = ref<Nullable<boolean>>(false);
  const formRef = ref<Nullable<UseTableMethod>>(null);

  let stopWatch: WatchStopHandle;

  if (tableProps && tableProps.columns) {
    tableProps.columns = renderAdColumns(tableProps.columns as AdColumn[]);
  }

  /** 注册 */
  function register(instance: TableActionType, formInstance: UseTableMethod) {
    isProdMode() &&
      onUnmounted(() => {
        tableRef.value = null;
        loadedRef.value = null;
      });

    if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) return;

    tableRef.value = instance;
    formRef.value = formInstance;
    tableProps && instance.setProps(getDynamicProps(tableProps));
    loadedRef.value = true;

    stopWatch?.();

    stopWatch = watch(
      () => tableProps,
      () => {
        tableProps && instance.setProps(getDynamicProps(tableProps));
      },
      {
        immediate: true,
        deep: true,
      },
    );
  }

  /** 获取高级表格实例 */
  function getTableInstance(): TableActionType {
    const table = unref(tableRef);
    if (!table) {
      error('尚未获取表实例，请在执行表操作时确保表已呈现！');
    }
    return table as TableActionType;
  }

  const methods: TableActionType & {
    getForm: () => FormActionType;
  } = {
    getForm: () => {
      return unref(formRef) as unknown as FormActionType;
    },
    /** 获取表格对象 */
    getTable: () => {
      return getTableInstance().getTable();
    },
    /** 打开详情表单 */
    openDetailForm: (formMode: FormModeEnum, record?: Recordable) => {
      return getTableInstance().openDetailForm(formMode, record);
    },
    /** 重载表格数据 */
    reload: (opt?: FetchParams) => {
      return getTableInstance().reload(opt);
    },
    /** 设置分页 */
    setPagination: (info: Partial<VxeGridPropTypes.PagerConfig>) => {
      return getTableInstance().setPagination(info);
    },
    /** 设置加载状态 */
    setLoading: (loading: boolean) => {
      return getTableInstance().setLoading(loading);
    },
    /** 获取表格数据 */
    getData: () => {
      return getTableInstance().getData();
    },
    /** 获取搜索信息 */
    getSearchInfo: () => {
      return getTableInstance().getSearchInfo();
    },
    /** 设置表格数据 */
    setData: <T = Recordable<any>,>(values: T[]) => {
      return getTableInstance().setData(values);
    },
    /** 设置表格属性 */
    setProps: (props: Partial<TableProps>) => {
      return getTableInstance().setProps(props);
    },
    /** 获取分页对象 */
    getPagination: () => {
      return getTableInstance().getPagination();
    },
    /** 获取列 */
    getColumns: () => {
      return getTableInstance().getColumns();
    },
    // /** 事件 */
    // emit: getTableInstance().emit,
  };

  return [register, methods];
}

//#region 渲染高级表格列集合
/**
 * 渲染高级列集合
 * @param columns 列集合
 * @returns 处理后的高级列集合
 */
export function renderAdColumns(columns: AdColumn[]): AdColumn[] {
  const data: AdColumn[] = [];

  columns.forEach((item) => {
    const newItem = { ...item };
    // 默认可拖动调整宽度
    if (newItem.resizable === undefined || newItem.resizable === null) {
      newItem.resizable = true;
    }
    // 默认表头居中
    if (newItem.headerAlign === undefined || newItem.headerAlign === null) {
      newItem.headerAlign = 'center';
    }
    // 默认当内容过长时显示为省略号
    if (newItem.showOverflow === undefined || newItem.showOverflow === null) {
      newItem.showOverflow = 'tooltip';
    }
    // newItem.cellRender = (value, row, index) => {
    //   //表体的数据列样式
    //   console.log(value, row, index); //本列的值,所有行数据包括本列,第几列
    //   const obj = {
    //     children: value,
    //     attrs: {},
    //   };
    //   obj.attrs.align = 'right';
    //   return obj;
    // };
    //渲染列样式
    switch (newItem.dataType) {
      case 'enum':
        if (!newItem.align) {
          newItem.align = 'center';
        }
        // if (
        //   (!newItem.enumData || newItem.enumData?.length <= 0) &&
        //   newItem.editComponent === 'ApiSelect' &&
        //   newItem.editComponentProps?.api
        // ) {
        //   //TODO:这个地方远程请求是有问题的（异步原因），需要在调用组件前手动获取值后赋值
        //   const apiFunction = newItem.editComponentProps.api;
        //   if (isFunction(apiFunction)) {
        //     apiFunction(newItem.editComponentProps?.params).then((res: EnumSchema[]) => {
        //       newItem.enumData = res;
        //     });
        //   }
        // }
        if (!newItem.slots?.default && newItem.enumData && newItem.enumData.length > 0) {
          newItem.slots = {
            ...newItem.slots,
            default: ({ row, column }) => {
              const val = row[column.field];
              if (isNumber(val) || isString(val)) {
                const currentEnum = newItem.enumData?.find((m) => {
                  return m.value === val;
                });
                if (!currentEnum) {
                  return val;
                }
                if (!currentEnum.tag) {
                  return currentEnum.label;
                }
                return h(
                  Tag,
                  {
                    closable: false,
                    color: currentEnum.tagColor,
                    icon: currentEnum.tagIcon,
                  },
                  { default: () => currentEnum.label || currentEnum.value },
                );
              }
              return <div>{val}</div>;
            },
          };
        }
        break;
      case 'integer':
      case 'number':
      case 'quantity':
      case 'price':
      case 'amount':
      case 'rate':
      case 'percentage':
      case 'measure':
        if (!newItem.align) {
          newItem.align = 'right';
        }
        break;
      case 'string':
      case 'text':
      case 'email':
      case 'mobile':
      case 'url':
      case 'ipv4':
      case 'ipv6':
      case 'idcard':
        if (!newItem.align) {
          newItem.align = 'left';
        }
        break;
      case 'password':
        if (!newItem.align) {
          newItem.align = 'left';
        }
        if (!newItem.formatter) {
          newItem.formatter = () => '******';
        }
        break;
      case 'guid':
        if (!newItem.align) {
          newItem.align = 'center';
        }
        break;
      case 'boolean':
        if (!newItem.align) {
          newItem.align = 'center';
        }
        if (!newItem.slots?.default) {
          newItem.slots = {
            ...newItem.slots,
            default: ({ row, column }) => {
              const val = row[column.field];
              if (isBoolean(val)) {
                return h(Icon, {
                  icon: val ? 'ant-design:check-outlined' : 'ant-design:close-outlined',
                  color: val ? '#48a5ea' : '#e25e37',
                });
              }
              return <div>{val}</div>;
            },
          };
        }
        break;
      case 'datetime':
      case 'date':
      case 'time':
        if (!newItem.align) {
          newItem.align = 'center';
        }
        let dateFormat = '';
        if (!newItem.formatter) {
          dateFormat =
            item.dataType === 'datetime'
              ? 'YYYY-MM-DD HH:mm:ss'
              : item.dataType === 'date'
                ? 'YYYY-MM-DD'
                : 'HH:mm:ss';
        }
        if (dateFormat !== undefined && dateFormat !== null && dateFormat !== '') {
          newItem.formatter = ({ cellValue }) => formatToDate(cellValue, dateFormat);
        }
        break;
      case 'array':
        if (!newItem.formatter) {
          newItem.formatter = ({ cellValue }) =>
            isArray(cellValue) ? expandAndToString(cellValue as unknown as any[]) : cellValue;
        }
        break;
    }
    data.push(newItem);
  });

  return data;
}
//#endregion
